/*
 * Copyright (C) 2010-2011 Graz University of Technology, Austria. All Rights reserved. 
 *
 * Contact: Simone Kopeinik <simone.kopeinik@tugraz.at>
 * 	   Graz University of Technology, Knowledge Management Institute, Brückenkopfgasse 1/6, 8020 Graz 	
 * 	   <http://www.kmi.tugraz.at/>
 * 
 * This software is part of the TARGET platform developed by the
 * TARGET EC-funded project www.reachyourtarget.org
 *
 * This software is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * The GNU General Public License is available at <http://www.gnu.org/licenses/>.
 *
 */
package at.tugraz.kmi.css.testcommons;

import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;

import org.testng.IObjectFactory;
import org.testng.ITestContext;
import org.testng.annotations.ObjectFactory;
import org.testng.internal.ObjectFactoryImpl;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;

/**
 * Light injector implementation for TestNG, based on google-guice.
 * 
 * @author Simone Tripodi
 * @version $Id$
 */
public abstract class AbstractGuiceObjectFactory implements IObjectFactory {

	/**
	 * The serial version UID.
	 */
	private static final long		serialVersionUID	= 1L;

	/**
	 * This class logger.
	 */
	private final Logger			log					= Logger.getLogger(this
																.getClass()
																.getName());

	/**
	 * The default TestNG provided implementation of {@link IObjectFactory}.
	 */
	private final ObjectFactoryImpl	creator				= new ObjectFactoryImpl();

	/**
	 * The Injector used to inject dependencies into Test Case classes.
	 */
	private final Injector			injector;

	/**
	 * Instantiates a new ObjectFactory relying on Google Guice.
	 */
	public AbstractGuiceObjectFactory() {
		this.injector = Guice.createInjector(this.createTestContext());
	}

	/**
	 * Builds the test module list.
	 * 
	 * @return the test module list.
	 */
	protected abstract List<Module> createTestContext();

	/**
	 * {@inheritDoc}
	 */
	@Override
	public final Object newInstance(
			@SuppressWarnings("unchecked") final Constructor constructor,
			final Object... args) {

		this.log.finer("Creating new object of type '"
				+ constructor.getDeclaringClass().getName()
				+ "' using constructor '" + constructor + "' with arguments "
				+ Arrays.deepToString(args));

		Object obj = this.creator.newInstance(constructor, args);

		this.log.finer("Created objeect of type '" + obj.getClass().getName()
				+ "', injecting dependencies..");

		this.injector.injectMembers(obj);

		this.log.finer("Dependencies successfully injected in object of type '"
				+ obj.getClass().getName() + "'");

		return obj;
	}

	@ObjectFactory
	public final IObjectFactory init(final ITestContext context) {
		return this;
	}

}